home *** CD-ROM | disk | FTP | other *** search
- #include "includes.h"
-
- Parameter *Encode_Parm;
- BitMap *Encode_Block;
- BitMap *Encode_Image;
- unsigned char Encode_DeltaQuant;
- int Encode_PostTrans;
-
-
- /**************************************|****************************************
- Routine : GetClassCount
- Input par: FeatureSpace *S (pointer to feature space)
- int *Index (pointer to index in the feature space)
- Output par: unsigned long (count of subclass members)
- Function : Finds the number of nodes in a given subclass of a feature space.
- ***************************************|***************************************/
-
- unsigned long GetClassCount(FeatureSpace *S,int *Index)
- {
- int i;
- Grid *tmp=S->GridArray;
- GridTerm *T;
- for(i=0;i<S->Dimension;i++) tmp=tmp->Next[Index[i]];
- T=(GridTerm *)tmp;
- return T->Count;
- }
-
- /**************************************|****************************************
- Routine : FindNearest
- Input par: ListNode *List (pointer to list of domain blocks)
- PoolNode *Range(range block to compare to)
- int dim (feature dimension)
- int MaxList (maximum nodes in list)
- Output par: ListNode * (pointer to found list)
- Function : Finds the nearest domain blocks for a given range block in the
- n-dimensional feature space.
- ***************************************|***************************************/
-
- ListNode *FindNearest(ListNode *List,PoolNode *Range,int dim, int MaxList)
- {
- ListNode *s=List,*NewList=GimmeAListNode();/* this routine has to be very quick since its */
- ListNode *Tmp,*p; /* called at least once for every edge range block */
- register unsigned int i;
- register unsigned long d;
- unsigned int Found=1;
- register long t;
-
- NewList->Next=NewList->Pred=NewList;
- NewList->Domain=List->Domain;
-
- d=0; /* find first distance */
- i=dim;
- while(i--)
- {
- t=Range->Distance[i]-List->Domain->Distance[i];
- if (t>0) d += t; /* Manhattan distance for speed */
- else d -=t;
- }
-
- NewList->L=d; /* initialize new list */
- List=List->Next;
-
- while(List!=NULL)
- {
- d=0;
- i=dim;
- while(i--)
- {
- t=Range->Distance[i]-List->Domain->Distance[i];
- if (t>0) d += t; /* Manhattan distance for speed */
- else d -=t;
- }
-
- p=NewList;
-
- if(Found<=MaxList)
- {
- Found++;
-
- Tmp=GimmeAListNode();
- Tmp->Domain=List->Domain;
- Tmp->L=d;
-
- while((p->L<d) && (p->Next!=NewList)) p=p->Next;
-
- if(p->L<d) p=p->Next; /* check for last in list */
-
- Tmp->Pred=p->Pred;
- Tmp->Pred->Next=Tmp;
- Tmp->Next=p;
- p->Pred=Tmp;
- if (d<=NewList->L) NewList=Tmp; /* new list start */
- }
- else
- if (p->Pred->L>d)
- {
- while(p->L<d) p=p->Next;
-
- Tmp=NewList->Pred; /* last one in list */
- Tmp->Domain=List->Domain;
- Tmp->L=d;
-
- if(p->Next!=NewList && p!=NewList) /* new element not last in list */
- {
- NewList->Pred=Tmp->Pred; /* reset last list meber */
- NewList->Pred->Next=NewList;
-
- Tmp->Pred=p->Pred; /* insert member */
- Tmp->Pred->Next=Tmp;
- Tmp->Next=p;
- p->Pred=Tmp;
- }
- if (d<=NewList->L) NewList=Tmp; /* new list start */
- }
- List=List->Next;
- }
-
- FreeMeAList(s);
- return NewList;
- }
-
- /**************************************|****************************************
- Routine : BuildList
- Input par: FeatureSpace *S (pointer to a feature space)
- int *Index (pointer to index in a feature space)
- Output par: ListNode * (pointer created list)
- Function : Takes a subclass of a feature space (pointed out by the index) and
- builds a list of the blocks in the class.
- ***************************************|***************************************/
-
- ListNode *BuildList(FeatureSpace *S,int *Index)
- {
- int i;
- ListNode *Start,*List,*tmpList;
- Grid *tmp=S->GridArray;
- GridTerm *T;
-
- for(i=0;i<S->Dimension;i++) tmp=tmp->Next[Index[i]];
- T=(GridTerm *)tmp;
-
- if (T->Count==0) return (ListNode *)NULL;
-
- tmpList=T->Class;
- Start=List=GimmeAListNode();
- List->Info=T->Count;
- List->Domain=tmpList->Domain;
- tmpList=tmpList->Next;
-
- while (tmpList!=NULL)
- {
- ListNode *pp=GimmeAListNode();
-
- List->Next=pp;
- pp->Pred=List;
- List=List->Next;
- List->Domain=tmpList->Domain;
- tmpList=tmpList->Next;
- }
-
- List->Next=Start;
- Start->Pred=List;
-
- return Start;
- }
-
- /**************************************|****************************************
- Routine : InsertList
- Input par: ListNode *List (first list)
- ListNode *Xtra (second list)
- Output par: ListNode * (pointer to meged lists)
- Function : Merges to lists.
- ***************************************|***************************************/
-
- ListNode *InsertList(ListNode *List,ListNode *Xtra)
- {
- if(Xtra==NULL) return List;
- if(List==NULL) return Xtra;
-
- if (Xtra->Info==0) return List;
- if (List->Info==0) return Xtra;
-
- List->Pred->Next=Xtra;
- List->Pred=Xtra->Pred;
- Xtra->Pred->Next=List;
- Xtra->Pred=List->Pred;
- List->Info +=Xtra->Info;
-
- return List;
- }
-
- /**************************************|****************************************
- Routine : XtraSearch
- Input par: FeatureSpace *S (pointer the feature space)
- ListNode *List (list of blocks found so far)
- int *Index (pointer to rangenode index)
- int shell (the new shell to be search in (in the feature space))
- int dim (feature space dimension)
- int end (end flag)
- Output par: ListNode * (pointer to new list of blocks found)
- Function : A really special routine to do an extra search in an n-dimensional
- feature space. In the case where a normal search do not find enough
- blocks this routine is called. It looks searches in the surrounding
- of the original block index (shell).
- ***************************************|***************************************/
-
- ListNode *XtraSearch(FeatureSpace *S,ListNode *List,int *Index,int shell,int dim,int end)
- {
- int *NewIndex=GimmeAIntArray(S->Dimension); /* this routine gave me a lot of trouble ! */
- ListNode *L1,*L2;
- register int i,j;
- int d=dim,flag;
- d++;
-
- for(j= -shell;j<= shell;j++)
- {
- for(i=0;i<S->Dimension;i++) NewIndex[i]=Index[i];
- NewIndex[dim] += j;
-
- flag=TRUE;
- for(i=0;i<S->Dimension;i++) if (NewIndex[i]<0 || NewIndex[i]>=S->Size) flag=FALSE;
-
- if ((j== -shell || j== shell || end) && d==S->Dimension && flag)
- {
- L1=BuildList(S,NewIndex);
- List=InsertList(List,L1);
- }
-
- if (d<=S->Dimension && flag)
- {
- if (j== -shell || j== shell || end) L2=XtraSearch(S,NULL,NewIndex,shell,d,TRUE);
- else L2=XtraSearch(S,NULL,NewIndex,shell,d,FALSE);
- List=InsertList(List,L2);
- }
- }
-
- FreeMeAIntArray(NewIndex);
-
- return List;
- }
-
- /**************************************|****************************************
- Routine : SearchGrid
- Input par: FeatureSpace *DomainS (pointer to domain feature space)
- PoolNode *RangeNode (pointer to range block)
- int MinList,int MaxList (list sizes)
- Output par: ListNode * (pointer to list of domain blocks)
- Function : Find the nearest domain blocks for a given range block in an n-
- dimensional feature space.
- ***************************************|***************************************/
-
- ListNode *SearchGrid(FeatureSpace *DomainS,PoolNode *RangeNode,int MinList,int MaxList)
- {
- ListNode *SearchList;
- int Dim=DomainS->Dimension;
- int i,c=0;
-
- SearchList=BuildList(DomainS,RangeNode->Index);
-
- while (((SearchList==NULL) || (SearchList->Info<MinList)) && (c<10))
- {
- c++; /* he he : c plus plus */
- SearchList=XtraSearch(DomainS,SearchList,RangeNode->Index,c,0,FALSE);
- }
- if (c>1) vprintf(stderr," %d",c);
-
- if (SearchList==NULL)
- {
- vprintf(stderr,"\n search failed: ");
- for(i=0;i<Dim;i++) vprintf(stderr," %d ",RangeNode->Index[i]);
- exit(10);
- /* for(i=0;i<Dim;i++) I[i]=(DomainS->Size)>>1;
- SearchList=ExtraSearch(DomainS,SearchList,I,1);
- vprintf(stderr,".",SearchList->Info);*/
- }
-
- SearchList->Pred->Next=NULL; /* terminate list */
- if (SearchList->Info>MaxList)
- SearchList=FindNearest(SearchList,RangeNode,DomainS->Dimension,MaxList);
-
- return SearchList;
- }
-
- /**************************************|****************************************
- Routine : FindTransformation3D
- Input par: int XPos,int YPos, int ZPos (position of block to be encoded)
- int NSquare (the quadtree level)
- int BlockSize (range blocksize)
- PoolStructure *Pool (pool structure !)
- int MinList,int MaxList (list sizes)
- Output par: Transformation * (pointer to the found transformation)
- Function : Encodes a specific range block.
- ***************************************|***************************************/
-
- Transformation *FindTransformation(int XPos,int YPos, int NSquare,
- int BlockSize,PoolStructure *Pool,
- int MinList,int MaxList)
- {
- register unsigned int x,y,D=BlockSize<<1;
- Transformation *Trans=GimmeATransformation();
- PoolNode *RNode;
- ListNode *SearchList,*List;
- float *Features;
-
- Trans->BlockSize=BlockSize;
- Trans->D=D;
-
- RNode=Pool->RangeNodes[XPos/BlockSize][YPos/BlockSize];
- Features=RNode->Features;
-
- Encode_Block->XSize=Encode_Block->YSize=BlockSize;
-
- if(RNode->Distance==NULL)
- {
- Trans->Type=SHADEBLOCK; /* find shade transformation */
- Trans->g0 =Features[MEAN];
- }
- else /* find edge transformtion */
- {
- float Alpha,temp,tt;
- int Deltag;
- register long Bestdm=LONG_MAX,dm,Newdm;
- PoolNode *DNode;
- BitMap *tempimg;
- int tn,Count=0;
- register unsigned int i,j,x,y;
-
- Trans->Type=EDGEBLOCK;
- if(Encode_Parm->TPostProcess>=0)
- List=SearchList=SearchGrid(Pool->DomainSpace,RNode,MinList+POSTLISTEXTRA,MaxList+POSTLISTEXTRA);
- else
- List=SearchList=SearchGrid(Pool->DomainSpace,RNode,MinList,MaxList);
-
- while ((List->Next!=NULL) && (Count<MaxList) && (List->Next!=SearchList))
- {
- DNode=List->Domain;
- if (DNode->Features[VAR]==0.0) ErrorHandler(OUT_OF_RANGE,"Null variance"); /* should not happen ! */
-
- tempimg=Pool->SampledDomainBitmap;
- x=DNode->x>>1;
- y=DNode->y>>1;
-
- tt=temp=Features[STDDEV]/DNode->Features[STDDEV];
- /*
- temp=0.0;
- for(i=0;i<Encode_Block->XSize;i++)
- for(j=0;j<Encode_Block->YSize;j++)
- {
- temp += (float)tempimg->Map[x+i][y+j]*(float)Encode_Image->Map[XPos+i][YPos+j];
- }
-
- temp = temp/((float)Encode_Block->XSize*(float)Encode_Block->YSize);
- temp = (temp-(Features[MEAN])*(DNode->Features[MEAN]))/(DNode->Features[VAR]);
- */
- Alpha=MakeFloat(MakeRange(temp,Encode_Parm),Encode_Parm); /* quant alpha */
-
- /* vprintf(stderr,"\na %f\t\t%f\t%f\t%f",Alpha,temp,
- Features[MEAN]*DNode->Features[MEAN],temp-Features[MEAN]*DNode->Features[MEAN]);
- */
- Deltag=(int)(Features[MEAN]-DNode->Features[MEAN]*Alpha);
-
- if (Deltag> Encode_DeltaQuant) Deltag= Encode_DeltaQuant;
- if (Deltag<-Encode_DeltaQuant) Deltag=-Encode_DeltaQuant;
-
- for(i=0;i<Encode_Block->XSize;i++)
- for(j=0;j<Encode_Block->YSize;j++)
- Encode_Block->Map[i][j]=(tempimg->Map[x+i][y+j]*Alpha)+Deltag;
-
- dm=LONG_MAX;
- for(i=1;i<=8;i++)
- {
- Newdm=IsoAnddl2(Encode_Image,XPos,YPos,Encode_Block,BlockSize,i);
- if(Newdm<dm)
- {
- dm=Newdm;
- tn=i;
- }
- }
-
-
- if(dm<Bestdm)
- {
- Bestdm=dm;
- Trans->Alpha=Alpha;
- Trans->Deltag=Deltag;
- Trans->tn=tn-1;
- Trans->Domain=DNode;
- Trans->Distortion=dm;
- }
- Count++;
- List=List->Next;
-
- /* now check the distortion and postprocess if necessary */
-
- if (Count==MaxList && Encode_Parm->TPostProcess>=0)
- if(Encode_Parm->TPostProcess<Trans->Distortion/(BlockSize*BlockSize*BlockSize))
- {
- MaxList += POSTLISTEXTRA;
- Encode_PostTrans++;
- }
- }
-
- Trans->Distortion /= (BlockSize*BlockSize*BlockSize); /* normalize dl2 */
- FreeMeAList(SearchList);
- }
-
- if(NSquare>0) /* check if there are more sublevels */
- {
- if (Trans->Type==SHADEBLOCK)
- {
- const unsigned int B=BlockSize;
- const register unsigned int val=Trans->g0;
- register int tmp;
- register unsigned long Distortion=0;
-
- for(x=0;x<B;x++) /* insert distortion */
- for(y=0;y<B;y++)
- {
- tmp=Encode_Image->Map[XPos+x][YPos+y]-val;
- Distortion +=tmp*tmp;
- }
- Trans->Distortion=Distortion/(B*B*B);
- }
-
- if(Trans->Distortion>(unsigned long)Encode_Parm->TMainSub) /* check distortion */
- {
- Trans->Type=NOBLOCK; /* unmark main block */
-
- Trans->Sub=GimmeATransArray(2,2);
- for(x=0;x<2;x++)
- for(y=0;y<2;y++)
- Trans->Sub[x][y]= /* encode ALL sub blocks */
- FindTransformation(XPos+x*(BlockSize>>1),YPos+y*(BlockSize>>1),
- NSquare-1,BlockSize>>1,
- Pool->Next,MinList,MaxList);
- }
- }
-
- return Trans;
- }
-
- /**************************************|****************************************
- Routine : Encode3D
- Input par: BitMap3D *Image (pointer to the image to encode)
- int NSquare (number of octree square levels)
- int StartBlockSize (maximum range block size)
- PoolStructure *Pool(pointer to poolstructure)
- Parameter *Pa (pointer to parameters)
- int MinList,int MaxList (list sizes)
- Output par: Transformation **** (pointer to 3d array of transformations)
- Function : Encodes the image. Finds the a fractal transformations for every
- range block.
- ***************************************|***************************************/
-
- Transformation ***Encode(BitMap *Image,int NSquare,int StartBlockSize,
- PoolStructure *Pool,Parameter *Pa,int MinList,int MaxList)
- {
- register unsigned int x,y;
- Transformation ***FCCodes=GimmeATransArray(Image->XSize/StartBlockSize,
- Image->YSize/StartBlockSize);
- vprintf(stderr,"\nEncoding...");
-
- Encode_Parm=Pa; /* make parmeters global for module */
- Encode_DeltaQuant=1<<(Pa->DBits-1)-1;
- Encode_Block=GimmeABitMap(StartBlockSize,StartBlockSize,Image->ImgType);
- Encode_Image=Image;
- Encode_PostTrans=0;
-
- for(x=0;x<Image->XSize/StartBlockSize;x++)
- {
- for(y=0;y<Image->YSize/StartBlockSize;y++)
- FCCodes[x][y]=FindTransformation(x*StartBlockSize,y*StartBlockSize,
- NSquare,StartBlockSize,Pool,MinList,MaxList);
-
- if (Quiet) fprintf(stderr,"%3.1f%c ",(float)(x*100)/Image->XSize,'%');
- else fprintf(stderr,"\n x:%3d y:%d =%3.1f%c",x*StartBlockSize,y*StartBlockSize,
- (float)(x*StartBlockSize*100)/Image->XSize,'%');
- }
-
- vprintf(stderr,"\n Post processed %d blocks",Encode_PostTrans);
- Encode_Block->XSize=StartBlockSize;
- Encode_Block->YSize=StartBlockSize;
-
- FreeMeABitMap(Encode_Block);
-
- return FCCodes;
- }
-